﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using ConfApp.Infrastructure;
using ConfApp.Models;
using ConfApp.Services;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Net.NetworkInformation;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Tasks;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Interactivity.InteractionRequest;
using Phone7.Fx.Preview;
using NetworkInterface = Microsoft.Phone.Net.NetworkInformation.NetworkInterface;

namespace ConfApp.ViewModels
{
    public class PodcastViewModel : ViewModel
    {
        private readonly IPodcastStore _podcastStore;
        private MediaElement _mediaElement;
        private DispatcherTimer _progressTimer;

        public PodcastViewModel(
            IPodcastStore podcastStore, 
            INavigationService navigationService) 
            : base(navigationService)
        {
            _podcastStore = podcastStore;
            Initialize();
        }

        private InteractionRequest<Notification> submitErrorInteractionRequest;
        private InteractionRequest<Notification> _stopMultimediaInteractionRequest;

        public IInteractionRequest SubmitErrorInteractionRequest
        {
            get { return this.submitErrorInteractionRequest; }
        }

        public IInteractionRequest StopMultimediaInteractionRequest
        {
            get { return this._stopMultimediaInteractionRequest; }
        }

        private void Initialize()
        {
            this.submitErrorInteractionRequest = new InteractionRequest<Microsoft.Practices.Prism.Interactivity.InteractionRequest.Notification>();
            this._stopMultimediaInteractionRequest = new InteractionRequest<Microsoft.Practices.Prism.Interactivity.InteractionRequest.Notification>();
            OnLoadedCommand = new DelegateCommand<PhoneApplicationPage>(OnLoaded);
            MediaOpenedCommand = new DelegateCommand<MediaElement>(MediaOpened, CanMediaOpened);
            MediaEndedCommand = new DelegateCommand<MediaElement>(MediaEnded, CanMediaEnded);
            MediaCurrentStateChangedCommand = new DelegateCommand<MediaElement>(MediaCurrentStateChanged, CanMediaCurrentStateChanged);
            PlayCommand = new DelegateCommand(Play, CanPlay);
            StopCommand = new DelegateCommand(Stop, CanStop);
            PauseCommand = new DelegateCommand(Pause, CanPause);
            TogglePlayCommand = new DelegateCommand(() =>
                                                        {
                                                            CheckMediaMode();
                                                            if(!IsMediaMode)
                                                                return;

                                                            if (CanPlay())
                                                            {
                                                                Play();
                                                            }
                                                            else if (CanPause())
                                                            {
                                                                Pause();
                                                            }
                                                        },
                                                    () =>
                                                        { return CanPlay() || CanPause(); });
            //NetworkChange.NetworkAddressChanged += (o,s)
            //                                       =>
            //                                           {
            //                                               if (!IsNetworkAvailable) 
            //                                                   if (CanStop()) Stop();
            //                                           };

    //this.IsBeingActivated();
        }

        public DelegateCommand<PhoneApplicationPage> OnLoadedCommand { get; set; }
        public void OnLoaded(PhoneApplicationPage param)
        {
            _mediaElement = (MediaElement)param.FindName("MediaPlayer");
            IsMediaOpened = false;
            if (IsNetworkAvailable)
            {
                CheckMediaMode();
                if (IsMediaMode) _mediaElement.Source = Url;
            }
            else
            {
                IsMediaMode = false;
            }
        }

        private bool IsMultimediaPlaying
        {
            get
            {
                Microsoft.Xna.Framework.FrameworkDispatcher.Update();
                return !Microsoft.Xna.Framework.Media.MediaPlayer.GameHasControl;
            }
        }

        private class NotificationContent
        {
            public string Content { get; set; }
            public MessageBoxButton Buttons { get; set; }
            public MessageBoxResult Result { get; set; }
        }

        private void CheckMediaMode()
        {
            if (!IsPlaying && IsMultimediaPlaying)
            {
                string content =
                    "Multimedija koja se izvršava u pozadini biće prekinuta. Da li ste saglasni?";
                this._stopMultimediaInteractionRequest.Raise(
                    new Notification
                        {
                            Title = "Sinergija 11",
                            Content = new NotificationContent
                            {
                                Content = content,
                                Buttons = MessageBoxButton.OKCancel
                            }
                        },
                    n =>
                    {
                        if ((n.Content as NotificationContent).Result == MessageBoxResult.OK)
                        {
                            //Microsoft.Xna.Framework.FrameworkDispatcher.Update();
                            Microsoft.Xna.Framework.Media.MediaPlayer.Stop();
                            IsMediaMode = true;
                        }
                        else
                        {
                            IsMediaMode = false;
                        }
                    });
            }
            else
            {
                //Microsoft.Xna.Framework.FrameworkDispatcher.Update();
                //Microsoft.Xna.Framework.Media.MediaPlayer.Stop();
                IsMediaMode = true;
            }
        }


        #region MediaOpenedCommand
        public DelegateCommand<MediaElement> MediaOpenedCommand { get; set; }
        public void MediaOpened(MediaElement param)
        {
            //_mediaElement = param;
            if (_progressTimer == null)
            {
                this._progressTimer = new DispatcherTimer();
                this._progressTimer.Interval = TimeSpan.FromSeconds(1);
                this._progressTimer.Tick += new EventHandler(this.ProgressTimer_Tick);
            }

            SetCurrentPosition();
            IsMediaOpened = true;

            if (_playOnOpening)
            {
                Play();
                _playOnOpening = false;
            } 
            
            RaisePropertyChanged(() => AppBarTogglePlayIconUrl);
            RaisePropertyChanged(() => AppBarTogglePlayText);
        }

        private bool CanMediaOpened(object param)
        {
            return true;
        }
        #endregion

        #region MediaEndedCommand
        public DelegateCommand<MediaElement> MediaEndedCommand { get; set; }
        public void MediaEnded(MediaElement param)
        {
            Stop();
        }

        private bool CanMediaEnded(object param)
        {
            return true;
        }
        #endregion



        #region MediaCurrentStateChangedCommand
        public DelegateCommand<MediaElement> MediaCurrentStateChangedCommand { get; set; }
        public void MediaCurrentStateChanged(MediaElement param)
        {
            RaisePropertyChanged(() => AppBarTogglePlayIconUrl);
            RaisePropertyChanged(() => AppBarTogglePlayText);
        }

        private bool CanMediaCurrentStateChanged(object param)
        {
            return true;
        }
        #endregion

        public bool IsNetworkAvailable
        {
            get
            {
                return NetworkInterface.NetworkInterfaceType != NetworkInterfaceType.None;                
            }
        }

        #region PlayCommand
        public DelegateCommand PlayCommand { get; set; }
        private bool _playOnOpening = false;
        private bool _failed = false;

        public void Play()
        {
            if (!CanPlay()) return;
            if (_failed)
            {
                _mediaElement.Source = Url;
                _playOnOpening = true;
                _failed = false;
            }
            else
            {
                if (_mediaElement.Source == null || !IsMediaOpened)
                {
                    _mediaElement.Source = Url;
                    _playOnOpening = true;
                    return;
                }
                _mediaElement.Play();
                _progressTimer.Start();
                //IsPlaying = true;
                RaisePropertyChanged(() => AppBarTogglePlayIconUrl);
                RaisePropertyChanged(() => AppBarTogglePlayText);
            }
        }

        private bool CanPlay()
        {
            if (!IsMediaMode) return false;
            if(!IsNetworkAvailable || _mediaElement==null)
            {
                IsMediaMode = false;
                this.submitErrorInteractionRequest.Raise(
                    new Notification { Title = "Greška pri učitavanju", Content = "Internet veza nije trenutno dostupna" },
                    n => { });
                return false;
            }
            else
            {
                IsMediaMode = true;
            }
            if (_mediaElement.CurrentState != MediaElementState.Playing)
            {
                return true;
            }
            return false;
        }
        #endregion

        #region StopVideoCommand
        public DelegateCommand StopCommand { get; set; }
        public void Stop()
        {
            if(!CanStop())return;
            //IsPlaying = false;
            _mediaElement.Stop();
            _progressTimer.Stop();
            SetCurrentPosition();
            RaisePropertyChanged(() => AppBarTogglePlayIconUrl);
            RaisePropertyChanged(() => AppBarTogglePlayText);
        }

        private bool CanStop()
        {
            bool canStop = false;

            if (_mediaElement != null && _progressTimer != null)
            {
                canStop = true;
            }

            return canStop;
        }
        #endregion

        #region PauseCommand
        public DelegateCommand PauseCommand { get; set; }
        public void Pause()
        {
            if (!CanPause()) return;
            if (_mediaElement.CurrentState == MediaElementState.Playing)
            {
                // If we can Pause the Video, Pause it
                if (_mediaElement.CanPause)
                {
                    // Pause Video
                    _mediaElement.Pause();
                }
                else
                {
                    // We can't pause the Video so Stop it
                    _mediaElement.Stop();
                }

                if (_progressTimer.IsEnabled)
                {
                    _progressTimer.Stop();
                }
                //IsPlaying = false;
            }
            else
            {
                // The Media is not Playing so we are Paused
                // Play Video
                _mediaElement.Play();
                _progressTimer.Start();
                //IsPlaying = true;
            }
            RaisePropertyChanged(() => AppBarTogglePlayIconUrl);
            RaisePropertyChanged(() => AppBarTogglePlayText);
        }

        private bool CanPause()
        {
            bool CanPause = false;

            if (_mediaElement != null)
            {
                // Only allow this Command if paused or Playing
                if ((_mediaElement.CurrentState == MediaElementState.Paused)
                    || (_mediaElement.CurrentState == MediaElementState.Playing))
                {
                    CanPause = true;
                }
            }

            return CanPause;
        }
        #endregion

        #region Time display
        private void ProgressTimer_Tick(object sender, EventArgs e)
        {
            SetCurrentPosition();
        }

        private void SetCurrentPosition()
        {
            // If the Media play is complete stop the media
            //if (CurrentPositionProperty > 0)
            //{
            //    if (CurrentPositionProperty >= TotalDurationProperty)
            //    {
            //        CurrentPositionProperty = 0;
            //        Stop();
            //    }
            //}

            // Update the time text e.g. 01:50 / 03:30
            CurrentProgressProperty = string.Format(
                "{0}:{1} / {2}:{3}",
                Math.Floor(_mediaElement.Position.TotalMinutes).ToString("00"),
                _mediaElement.Position.Seconds.ToString("00"),
                Math.Floor(_mediaElement.NaturalDuration.TimeSpan.TotalMinutes).ToString("00"),
                _mediaElement.NaturalDuration.TimeSpan.Seconds.ToString("00"));

            CurrentPositionProperty = _mediaElement.Position.TotalSeconds;
            TotalDurationProperty = _mediaElement.NaturalDuration.TimeSpan.TotalSeconds;
            MediaBufferingProperty = (_mediaElement.CurrentState == MediaElementState.Buffering);
            MediaBufferingTimeProperty = String.Format("Učitavam {0} %", (_mediaElement.BufferingProgress * 100).ToString("##"));
        }
        #endregion

        #region CurrentProgressProperty
        private string _currentProgressProperty;
        public string CurrentProgressProperty
        {
            get
            {
                return this._currentProgressProperty;
            }
            set
            {
                this._currentProgressProperty = value;
                this.RaisePropertyChanged(() => CurrentProgressProperty);
            }
        }
        #endregion

        #region TotalDurationProperty
        private double _totalDurationProperty;
        public double TotalDurationProperty
        {
            get
            {
                return this._totalDurationProperty;
            }
            set
            {
                this._totalDurationProperty = value;
                this.RaisePropertyChanged(() => TotalDurationProperty);
            }
        }
        #endregion

        #region CurrentPositionProperty
        private double _currentPositionProperty;
        public double CurrentPositionProperty
        {
            get
            {
                return this._currentPositionProperty;
            }
            set
            {
                this._currentPositionProperty = value;
                this.RaisePropertyChanged(() => CurrentPositionProperty);
            }
        }
        #endregion

        #region MediaBufferingProperty
        private bool _mediaBufferingProperty;
        public bool MediaBufferingProperty
        {
            get
            {
                return this._mediaBufferingProperty;
            }
            set
            {
                this._mediaBufferingProperty = value;
                this.RaisePropertyChanged(() => MediaBufferingProperty);
            }
        }
        #endregion

        #region MediaBufferingTimeProperty
        private string _mediaBufferingTimeProperty;
        public string MediaBufferingTimeProperty
        {
            get
            {
                return this._mediaBufferingTimeProperty;
            }
            set
            {
                this._mediaBufferingTimeProperty = value;
                this.RaisePropertyChanged(()=>MediaBufferingTimeProperty);
            }
        }
        #endregion

        private int? _id;
        private Podcast _podcast;
        public Podcast Podcast
        {
            get
            {
                var id = int.Parse(NavigationService.CurrentSource
                                       .OriginalString.Split('=')[1]);
                if (_id == null || (_id != id))
                {
                    _id = id;
                    _podcast = _podcastStore.FindPodcast(id);
                }
                return _podcast;
            }
        }

        public string Title { get { return Podcast.Title; } }
        public string Details { get { return Podcast.Details
            .Replace("&amp;", "&")
            .Replace("&quot;", "\"")
            .Replace("\n",Environment.NewLine); } }
        public string Author { get { return Podcast.Author; } }

        public Uri Url 
        { 
            get
            {
                return new Uri(Podcast.Url);
            } 
        }

        public DateTime PublishingDate { get { return Podcast.Date; } }

        public string Info
        {
            get
            {
                var dt = Time.Now - PublishingDate;
                if (dt.TotalMinutes < 1)
                {
                    return string.Format("malopre");
                }
                if (dt.TotalMinutes < 60)
                {
                    return string.Format("pre {1} min", Author, (int)dt.TotalMinutes);
                }
                else if (dt.TotalHours < 24)
                {
                    return string.Format("pre {1} h", Author, (int)dt.TotalHours);
                }
                return string.Format("{1:dd.MM.yyyy.}", Author, PublishingDate);
            }
        }

        private bool _isMediaMode;
        public bool IsMediaMode
        {
            get { return _isMediaMode; }
            set
            {
                if (_isMediaMode != value)
                {
                    _isMediaMode = value;
                    RaisePropertyChanged(() => this.IsMediaMode);
                }
            }
        }

        private bool _isMediaOpened;
        public bool IsMediaOpened
        {
            get { return _isMediaOpened; }
            set
            {
                if (_isMediaOpened != value)
                {
                    _isMediaOpened = value;
                    RaisePropertyChanged(() => this.IsMediaOpened);
                }
            }
        }
        public bool IsPlaying 
        { 
            get { return 
                _mediaElement != null &&
                _mediaElement.CurrentState == MediaElementState.Playing; }
        }

        public Uri AppBarTogglePlayIconUrl
        {
            get
            {
                return new Uri(!IsPlaying ?
                    "/Resources/Icons/appbar.transport.play.rest.png" :
                    "/Resources/Icons/appbar.transport.pause.rest.png", UriKind.Relative);
            }
        }

        public string AppBarTogglePlayText
        {
            get
            {
                return !IsPlaying ?
                    "play" :
                    "pause";
            }
        }

        public DelegateCommand TogglePlayCommand { get; set; }

        public override void IsBeingDeactivated()
        {
  
        }

        public override sealed void IsBeingActivated()
        {
            //IsPlaying = false;
            _progressTimer.Stop();
        }

        public override void IsBeingObscured(bool isLocked)
        {
            if (_progressTimer != null)
            {
                _progressTimer.Stop();
            }
        }

        public override void IsBeingUnobscured()
        {
            if (_progressTimer != null)
            {
                _progressTimer.Start();
            }
        }
    }
}
